<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 1.5.3">
<title>Contracts in an external repository 2.4.5-SNAPSHOT</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<style>
/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
/* Remove comment around @import statement below when using as a custom stylesheet */
/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
audio,canvas,video{display:inline-block}
audio:not([controls]){display:none;height:0}
[hidden],template{display:none}
script{display:none!important}
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
body{margin:0}
a{background:transparent}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
abbr[title]{border-bottom:1px dotted}
b,strong{font-weight:bold}
dfn{font-style:italic}
hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:"\201C" "\201D" "\2018" "\2019"}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}
input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
body{-webkit-font-smoothing:antialiased}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.center{margin-left:auto;margin-right:auto}
.spread{width:100%}
p.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6}
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:none}
p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol,ul.no-bullet,ol.no-bullet{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
ul.square{list-style-type:square}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.no-bullet{list-style:none}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
abbr{text-transform:none}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
blockquote cite:before{content:"\2014 \0020"}
blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
table thead,table tfoot{background:#f7f8f7;font-weight:bold}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
body{tab-size:4}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:" ";display:table}
.clearfix:after,.float-group:after{clear:both}
*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menu{color:rgba(0,0,0,.8)}
b.button:before,b.button:after{position:relative;top:-1px;font-weight:400}
b.button:before{content:"[";padding:0 3px 0 2px}
b.button:after{content:"]";padding:0 2px 0 3px}
p a>code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:" ";display:table}
#header:after,#content:after,#footnotes:after,#footer:after{clear:both}
#content{margin-top:1.25em}
#content:before{content:none}
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}
#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span:before{content:"\00a0\2013\00a0"}
#header .details br+span.author:before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
#header .details br+span#revremark:before{content:"\00a0|\00a0"}
#header #revnumber{text-transform:capitalize}
#header #revnumber:after{content:"\00a0"}
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #efefed;padding-bottom:.5em}
#toc>ul{margin-left:.125em}
#toc ul.sectlevel0>li>a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media only screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}
@media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2>ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
#content #toc>:first-child{margin-top:0}
#content #toc>:last-child{margin-bottom:0}
#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:rgba(255,255,255,.8);line-height:1.44}
.sect1{padding-bottom:.625em}
@media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}}
.sect1+.sect1{border-top:1px solid #efefed}
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
table.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0}
.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)}
table.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit}
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock>table td.icon{text-align:center;width:80px}
.admonitionblock>table td.icon img{max-width:none}
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
.exampleblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child{margin-bottom:0}
.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
.sidebarblock>:first-child{margin-top:0}
.sidebarblock>:last-child{margin-bottom:0}
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}
.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}
@media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
@media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.listingblock>.content{position:relative}
.listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
.listingblock:hover code[data-lang]:before{display:block}
.listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999}
.listingblock.terminal pre .command:not([data-prompt]):before{content:"$"}
table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
table.pyhltable td.code{padding-left:.75em;padding-right:0}
pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}
pre.pygments .lineno{display:inline-block;margin-right:.25em}
table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote:before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}
.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}
.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}
.quoteblock .quoteblock blockquote:before{display:none}
.verseblock{margin:0 1em 1.25em 1em}
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract{margin:0 0 1.25em 0;display:block}
.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0}
.quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none}
table.tableblock{max-width:100%;border-collapse:separate}
table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all th.tableblock,table.grid-all td.tableblock{border-width:0 1px 1px 0}
table.grid-all tfoot>tr>th.tableblock,table.grid-all tfoot>tr>td.tableblock{border-width:1px 1px 0 0}
table.grid-cols th.tableblock,table.grid-cols td.tableblock{border-width:0 1px 0 0}
table.grid-all *>tr>.tableblock:last-child,table.grid-cols *>tr>.tableblock:last-child{border-right-width:0}
table.grid-rows th.tableblock,table.grid-rows td.tableblock{border-width:0 0 1px 0}
table.grid-all tbody>tr:last-child>th.tableblock,table.grid-all tbody>tr:last-child>td.tableblock,table.grid-all thead:last-child>tr>th.tableblock,table.grid-rows tbody>tr:last-child>th.tableblock,table.grid-rows tbody>tr:last-child>td.tableblock,table.grid-rows thead:last-child>tr>th.tableblock{border-bottom-width:0}
table.grid-rows tfoot>tr>th.tableblock,table.grid-rows tfoot>tr>td.tableblock{border-width:1px 0 0 0}
table.frame-all{border-width:1px}
table.frame-sides{border-width:0 1px}
table.frame-topbot{border-width:1px 0}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock>code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
td>div.verse{white-space:pre}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.unstyled,ol.unnumbered,ul.checklist,ul.none{list-style-type:none}
ul.unstyled,ol.unnumbered,ul.checklist{margin-left:.625em}
ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1em;font-size:.85em}
ul.checklist li>p:first-child>input[type="checkbox"]:first-child{width:1em;position:relative;top:1px}
ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden}
ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block}
ul.inline>li>*{display:block}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist>table,.colist>table{border:0;background:none}
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist>table tr>td:first-of-type{padding:0 .75em;line-height:1}
.colist>table tr>td:last-of-type{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
.imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0}
.imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em}
.imageblock>.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
.gist .file-data>table td.line-data{width:99%}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background-color:#00fafa}
.black{color:#000}
.black-background{background-color:#000}
.blue{color:#0000bf}
.blue-background{background-color:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background-color:#fa00fa}
.gray{color:#606060}
.gray-background{background-color:#7d7d7d}
.green{color:#006000}
.green-background{background-color:#007d00}
.lime{color:#00bf00}
.lime-background{background-color:#00fa00}
.maroon{color:#600000}
.maroon-background{background-color:#7d0000}
.navy{color:#000060}
.navy-background{background-color:#00007d}
.olive{color:#606000}
.olive-background{background-color:#7d7d00}
.purple{color:#600060}
.purple-background{background-color:#7d007d}
.red{color:#bf0000}
.red-background{background-color:#fa0000}
.silver{color:#909090}
.silver-background{background-color:#bcbcbc}
.teal{color:#006060}
.teal-background{background-color:#007d7d}
.white{color:#bfbfbf}
.white-background{background-color:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background-color:#fafa00}
span.icon>.fa{cursor:default}
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note:before{content:"\f05a";color:#19407c}
.admonitionblock td.icon .icon-tip:before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900}
.admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400}
.admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]:after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@media print{@page{margin:1.25cm .75cm}
*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
a[href^="http:"]:not(.bare):after,a[href^="https:"]:not(.bare):after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]:after{content:" (" attr(title) ")"}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}
.sect1{padding-bottom:0!important}
.sect1+.sect1{border:0!important}
#header>h1:first-child{margin-top:1.25rem}
body.book #header{text-align:center}
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span:before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
.listingblock code[data-lang]:before{display:block}
#footer{background:none!important;padding:0 .9375em}
#footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
</style>
<style>
.hidden {
	display: none;
}

.switch {
	border-width: 1px 1px 0 1px;
	border-style: solid;
	border-color: #7a2518;
	display: inline-block;
}

.switch--item {
	padding: 10px;
	background-color: #ffffff;
	color: #7a2518;
	display: inline-block;
	cursor: pointer;
}

.switch--item.selected {
	background-color: #7a2519;
	color: #ffffff;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.min.js"></script>
<script type="text/javascript">
function addBlockSwitches() {
	$('.primary').each(function() {
		primary = $(this);
		createSwitchItem(primary, createBlockSwitch(primary)).item.addClass("selected");
		primary.children('.title').remove();
	});
	$('.secondary').each(function(idx, node) {
		secondary = $(node);
		primary = findPrimary(secondary);
		switchItem = createSwitchItem(secondary, primary.children('.switch'));
		switchItem.content.addClass('hidden');
		findPrimary(secondary).append(switchItem.content);
		secondary.remove();
	});
}

function createBlockSwitch(primary) {
	blockSwitch = $('<div class="switch"></div>');
	primary.prepend(blockSwitch);
	return blockSwitch;
}

function findPrimary(secondary) {
	candidate = secondary.prev();
	while (!candidate.is('.primary')) {
		candidate = candidate.prev();
	}
	return candidate;
}

function createSwitchItem(block, blockSwitch) {
	blockName = block.children('.title').text();
	content = block.children('.content').first().append(block.next('.colist'));
	item = $('<div class="switch--item">' + blockName + '</div>');
	item.on('click', '', content, function(e) {
		$(this).addClass('selected');
		$(this).siblings().removeClass('selected');
		e.data.siblings('.content').addClass('hidden');
		e.data.removeClass('hidden');
	});
	blockSwitch.append(item);
	return {'item': item, 'content': content};
}

$(addBlockSwitches);
</script>
</head>

<body class="article toc2 toc-left">
<div id="header">
<h1>Contracts in an external repository 2.4.5-SNAPSHOT</h1>
<div id="toc" class="toc2">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#_scenarios">Scenarios</a></li>
<li><a href="#_flow">Flow</a></li>
<li><a href="#_tutorial">Tutorial</a>
<ul class="sectlevel2">
<li><a href="#_consumer_flow_1">Consumer flow 1</a>
<ul class="sectlevel3">
<li><a href="#_ide_setup">IDE setup</a></li>
<li><a href="#_cloning_the_repo_with_contracts">Cloning the repo with contracts</a></li>
<li><a href="#_adding_dependencies_in_the_repo_with_contracts">Adding dependencies in the repo with contracts</a></li>
<li><a href="#_creating_the_proper_folder_structure">Creating the proper folder structure</a></li>
<li><a href="#_defining_first_http_contract">Defining first HTTP contract</a></li>
<li><a href="#_defining_the_second_http_contract">Defining the Second HTTP Contract</a></li>
<li><a href="#_defining_the_first_messaging_contract">Defining the First Messaging Contract</a></li>
<li><a href="#_defining_second_messaging_contract">Defining second messaging contract</a></li>
<li><a href="#_setting_up_spring_cloud_contract_in_the_producer_contracts_config_file_inside_the_contracts_repo">Setting up Spring Cloud Contract in the Producer Contracts Config File inside the Contracts Repo</a></li>
<li><a href="#_writing_the_missing_consumer_http_implementation">Writing the missing consumer HTTP implementation</a></li>
<li><a href="#_turning_on_stub_runner_in_http_consumer_tests">Turning on Stub Runner in HTTP consumer tests</a></li>
<li><a href="#_playing_with_the_http_contracts">Playing with the HTTP contracts</a></li>
<li><a href="#_writing_the_missing_consumer_messaging_implementation">Writing the missing consumer messaging implementation</a></li>
<li><a href="#_turning_on_stub_runner_in_messaging_consumer_tests">Turning on Stub Runner in messaging consumer tests</a></li>
</ul>
</li>
<li><a href="#_producer_flow_1">Producer Flow 1</a>
<ul class="sectlevel3">
<li><a href="#_ide_setup_2">IDE setup</a></li>
<li><a href="#_install_the_contracts_locally">Install the Contracts Locally</a></li>
<li><a href="#_setting_up_the_spring_cloud_contract_dependencies_on_the_producer_side">Setting up the Spring Cloud Contract Dependencies on the Producer Side</a></li>
<li><a href="#_updating_contracts_from_the_pull_request">Updating Contracts from the Pull Request</a></li>
<li><a href="#_generating_tests_from_contracts">Generating tests from contracts</a></li>
<li><a href="#_fixing_broken_http_tests">Fixing broken HTTP tests</a></li>
<li><a href="#_fixing_broken_messaging_tests">Fixing broken messaging tests</a></li>
<li><a href="#_writing_the_missing_producer_messaging_implementation">Writing the missing producer messaging implementation</a></li>
</ul>
</li>
<li><a href="#_producer_flow_2">Producer Flow 2</a></li>
<li><a href="#_producer_flow_3">Producer Flow 3</a></li>
<li><a href="#_consumer_flow_2">Consumer flow 2</a></li>
<li><a href="#_generating_documentation_from_contracts">Generating documentation from contracts</a></li>
</ul>
</li>
<li><a href="#_solutions">Solutions</a>
<ul class="sectlevel2">
<li><a href="#_written_consumer_tests">Written consumer tests</a></li>
<li><a href="#_adding_spring_cloud_contract_dependency">Adding Spring Cloud Contract Dependency</a></li>
<li><a href="#_proposal_of_simple_contracts_by_consumer">Proposal of simple contracts by consumer</a></li>
<li><a href="#_missing_consumer_controller_code">Missing consumer controller code</a></li>
<li><a href="#_stub_logs">Stub Logs</a></li>
<li><a href="#_beer_request">Beer Request</a></li>
<li><a href="#_missing_listener_code">Missing listener code</a></li>
<li><a href="#_missing_triggers">Missing triggers</a></li>
<li><a href="#_messaging_dsls">Messaging DSLs</a></li>
<li><a href="#_producercontroller_implementation">ProducerController implementation</a></li>
<li><a href="#_beerrestbase">BeerRestBase</a></li>
<li><a href="#_beermessagingbase">BeerMessagingBase</a></li>
<li><a href="#_messaging_implementation">Messaging implementation</a></li>
</ul>
</li>
<li><a href="#_back_to_the_main_page">Back to the Main Page</a></li>
</ul>
</div>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>In this tutorial, we keep the contracts in a separate repository (a common arrangement).</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_scenarios">Scenarios</h2>
<div class="sectionbody">
<div class="paragraph">
<p>In most of the tutorials, you will be asked to code the following scenarios:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../images/beer_1.png" alt="beer 1">
</div>
<div class="title">Figure 1. Positive beer selling via HTTP</div>
</div>
<div class="paragraph">
<p>&#160;
&#160;</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../images/beer_2.png" alt="beer 2">
</div>
<div class="title">Figure 2. Negative beer selling via HTTP</div>
</div>
<div class="paragraph">
<p>&#160;
&#160;</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../images/msg_1.png" alt="msg 1">
</div>
<div class="title">Figure 3. Positive age verification via messaging</div>
</div>
<div class="paragraph">
<p>&#160;
&#160;</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../images/msg_2.png" alt="msg 2">
</div>
<div class="title">Figure 4. Negative age verification via messaging</div>
</div>
<div class="paragraph">
<p>&#160;
&#160;</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_flow">Flow</h2>
<div class="sectionbody">
<div class="imageblock">
<div class="content">
<img src="../images/flow.png" alt="flow">
</div>
<div class="title">Figure 5. Consumer Driven Contract flow</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_tutorial">Tutorial</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Using Consumer Driven Contracts is like using TDD at the architecture level. Let&#8217;s start
by writing a test on the consumer side.</p>
</div>
<div class="sect2">
<h3 id="_consumer_flow_1">Consumer flow 1</h3>
<div class="imageblock">
<div class="content">
<img src="../images/external_consumer_flow_1.png" alt="external consumer flow 1">
</div>
<div class="title">Figure 6. Interact with cloned repo with contracts</div>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<div class="title">Important</div>
</td>
<td class="content">
For the sake of this tutorial, our consumer application is called
<code>beer-api-consumer</code>.
</td>
</tr>
</table>
</div>
<div class="sect3">
<h4 id="_ide_setup">IDE setup</h4>
<div class="ulist">
<ul>
<li>
<p>Open in your IDE the <code>consumer</code> project (either via Maven or Gradle)</p>
</li>
<li>
<p>We have two objectives for HTTP</p>
<div class="ulist">
<ul>
<li>
<p>when a client wants a beer and has
e.g. name "marcin" and age 22 - the answer that we&#8217;ll respond with <code>THERE YOU GO</code></p>
</li>
<li>
<p>when a client is an underage and wants a beer and has
e.g. name "marcin" and age 17 - the answer that we&#8217;ll respond with <code>GET LOST</code></p>
</li>
</ul>
</div>
</li>
<li>
<p>and we have two objectives for messaging</p>
<div class="ulist">
<ul>
<li>
<p>when a verification message with <code>eligible</code> field equal to <code>true</code> was sent to the <code>verifications</code> channel
then we increment the <code>eligible</code> counter</p>
</li>
<li>
<p>when a verification message with <code>eligible</code> field equal to <code>false</code> was sent to the <code>verifications</code> channel
then we increment the <code>notEligible</code> counter</p>
</li>
</ul>
</div>
</li>
<li>
<p>Let&#8217;s start with HTTP.</p>
</li>
<li>
<p>Open the <code>BeerControllerTest</code> test. Since CDC is like TDD we have 2 tests that describe our beer selling features.
and we&#8217;re already providing some basic setup for you (in real TDD
example you&#8217;d have to code all of that yourself)</p>
</li>
<li>
<p>Technically speaking for both cases we want to use <code>MockMvc</code> to send a request to the <code>/beer</code> endpoint
with a JSON pojo containing <code>name</code> and <code>age</code>. From the controller we want to send a request to
<code><a href="http://localhost:8090/" class="bare">http://localhost:8090/</a></code> where the producer will be waiting for out requests. Let&#8217;s write the missing
tests body. (<a href="#_written_consumer_tests">Show solution</a>)</p>
</li>
<li>
<p>The first step in TDD is <code>red</code> - let&#8217;s run the tests and ensure that they are failing (in the controller
we return <code>null</code> instead of any meaningful value)</p>
</li>
<li>
<p>The problem is such that we don&#8217;t yet know what API we would like to have&#8230;&#8203; This is where we touch
the very essence of Consumer Driven Contracts. As consumers we want to drive the change of the API
that&#8217;s why, <strong>as consumers</strong>, we will work on the repo with contracts .</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_cloning_the_repo_with_contracts">Cloning the repo with contracts</h4>
<div class="paragraph">
<p>In this tutorial, we will not clone the repo with contracts. We&#8217;ll open it in the IDE.
The repository is called <code>beer_contracts</code>.</p>
</div>
</div>
<div class="sect3">
<h4 id="_adding_dependencies_in_the_repo_with_contracts">Adding dependencies in the repo with contracts</h4>
<div class="paragraph">
<p>Since we want the IDE to help us with code completion, let&#8217;s add the necessary Spring
Cloud Contract dependencies to the <code>pom.xml</code> under <code>beer_contracts</code> repo. You need to
add <code>spring-cloud-starter-contract-verifier</code> as a dependency, as shown in the following
example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
    &lt;artifactId&gt;spring-cloud-starter-contract-verifier&lt;/artifactId&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<div class="title">Important</div>
</td>
<td class="content">
Notice that we add the dependency in the <code>compile</code> scope, because we want all
of the contracts to be packaged as if they were production code. This task is performed
only once. When you add subsequent contracts, you won&#8217;t be able to add them again.
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="_creating_the_proper_folder_structure">Creating the proper folder structure</h4>
<div class="paragraph">
<p>In order to use a repository with contracts, you need to set up the folders so that they
adhere to the following convention:
** <code>/slash/separated/group/id/of/producer/producer-artifactid/consumer-name/</code>
In this tutorial, our producer has the following coordinates:
<code>com.example:beer-api-producer-external</code>. Our consumer will be called
<code>beer-api-consumer</code>.</p>
</div>
<div class="paragraph">
<p>Create the contract directory by running the following commands at the command line:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">$ cd beer_contracts
$ mkdir -p src/main/resources/contracts/com/example/beer-api-producer-external/beer-api-consumer/messaging
$ mkdir -p src/main/resources/contracts/com/example/beer-api-producer-external/beer-api-consumer/rest</code></pre>
</div>
</div>
<div class="paragraph">
<p>We have successfully created the proper folder structure. Time to add some contracts</p>
</div>
</div>
<div class="sect3">
<h4 id="_defining_first_http_contract">Defining first HTTP contract</h4>
<div class="paragraph">
<p>Let&#8217;s move to the
<code>src/main/resources/contracts/com/example/beer-api-producer-external/beer-api-consumer/</code>
folder. (<a href="#_proposal_of_simple_contracts_by_consumer">Show solution</a>).</p>
</div>
<div class="ulist">
<ul>
<li>
<p>You can define the contracts using Groovy DSL. Let&#8217;s create our first HTTP contract.</p>
<div class="ulist">
<ul>
<li>
<p>Under the <code>rest</code> folder create a file <code>shouldGrantABeerIfOldEnough.groovy</code></p>
</li>
<li>
<p>Call the <code>Contract.make</code> method to start defining the contract</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {

}</code></pre>
</div>
</div>
</li>
<li>
<p>You can call <code>description()</code> method to provide some meaningful description. TIP: You can use the
Groovy multiline String <code>""" """</code> to have all special characters escaped. Every new line in the String
will be converted into a new line character. Example</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
}</code></pre>
</div>
</div>
</li>
<li>
<p>Now call the <code>request { }</code> and <code>response { }</code> methods</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    request {
    }
    response {
    }
}</code></pre>
</div>
</div>
</li>
<li>
<p>Let&#8217;s assume that we&#8217;re interested in sending a <code>POST</code> method. Call <code>method POST()</code> or <code>method "POST"</code>.
TIP: In Groovy you don&#8217;t need to provide parentheses (in most cases). You can write either <code>method POST()</code>
or <code>method(POST())</code>. In both cases it&#8217;s the same syntax</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    request {
        method POST()
    }
    response {
    }
}</code></pre>
</div>
</div>
</li>
<li>
<p>Now we need to provide some URL. Let it be <code>/check</code>. Let&#8217;s write <code>url "/check"</code></p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    request {
        method POST()
        url "/check"
    }
    response {
    }
}</code></pre>
</div>
</div>
</li>
<li>
<p>Now time to define some body. We&#8217;ll leverage some of the Groovy power over here so if you&#8217;re lost
you can always check the <a href="http://groovy-lang.org/json.html">Groovy JSON documentation</a>. Let&#8217;s call the
<code>body()</code> method with brackets.</p>
</li>
<li>
<p>In Groovy you can use the map notation in such a way <code>[key: "value", secondKey: 2]</code>. In the same way
we can describe the body of a JSON. So in order to send a JSON looking like this <code>{ "age": 22, "name": "marcin" }</code>
we can create a map notation of <code>[age:22, name:"marcin"]</code>. The <code>body</code> method accepts a map and in Groovy
if a method accepts a map then the <code>[]</code> brackets can be omited. So you can either write
<code>body([age:22, name:"marcin"])</code> or <code>body(age:22, name:"marcin")</code>. The latter one contains less boilerplate
code so let&#8217;s write that one</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    request {
        method POST()
        url "/check"
        body(
            age: 22, name: "marcin"
            )
    }
    response {
    }
}</code></pre>
</div>
</div>
</li>
<li>
<p>Now time for the headers&#8230;&#8203; Call the <code>headers { }</code> method</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    request {
        method POST()
        url "/check"
        body(
            age: 22, name: "marcin"
            )
        headers {

        }
    }
    response {
    }
}</code></pre>
</div>
</div>
</li>
<li>
<p>Inside that method let&#8217;s define that we want to use the <code>Content-Type: "application/json</code> header. Just
call <code>contentType(applicationJson())</code> methods</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    request {
        method POST()
        url "/check"
        body(
            age: 22, name: "marcin"
            )
        headers {
            contentType(applicationJson())
        }
    }
    response {
    }
}</code></pre>
</div>
</div>
</li>
<li>
<p>Congratulations! You defined how you would like the contract for the request to look like! Time for the
response</p>
</li>
<li>
<p>In the <code>response</code> block we would like to define that that the status of our response will be 200.
Just call <code>status 200</code></p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    request {
        method POST()
        url "/check"
        body(
            age: 22, name: "marcin"
            )
        headers {
            contentType(applicationJson())
        }
    }
    response {
        status 200
    }
}</code></pre>
</div>
</div>
</li>
<li>
<p>We&#8217;d like our response to have some body. As you could have assumed there&#8217;s a <code>body</code> method here too.
We&#8217;ll now use another way of defining bodies (which is the less preferred option in Spring Cloud Contract
but still can be useful) - using String</p>
</li>
<li>
<p>We&#8217;re assuming that we would like to send back a field called <code>status</code> that will return <code>OK</code> when the
person can get the beer</p>
</li>
<li>
<p>Call the <code>body(""" { "status" : "OK" } """)</code>. That way you&#8217;re defining how the response body will look like
by providing the exact JSON value</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    request {
        method POST()
        url "/check"
        body(
            age: 22, name: "marcin"
            )
        headers {
            contentType(applicationJson())
        }
    }
    response {
        status 200
        body("""
            { "status" : "OK" }
        """)
    }
}</code></pre>
</div>
</div>
</li>
<li>
<p>Last thing to add are the response headers. We&#8217;re doing exactly the same thing as we have done previously
for the request. <code>headers { contentType(applicationJson()) }</code>.</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    request {
        method POST()
        url "/check"
        body(
            age: 22, name: "marcin"
            )
        headers {
            contentType(applicationJson())
        }
    }
    response {
        status 200
        body("""
            { "status" : "OK" }
        """)
        headers {
            contentType(applicationJson())
        }
    }
}</code></pre>
</div>
</div>
</li>
<li>
<p>Congratulations! You have created your first contract!</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_defining_the_second_http_contract">Defining the Second HTTP Contract</h4>
<div class="paragraph">
<p>Now it&#8217;s time for you to create the second contract. Under
<code>src/main/resources/contracts/com/example/beer-api-producer-external/beer-api-consumer/rest</code>,
create a file called <code>shouldRejectABeerIfTooYoung.groovy</code>.
If you get lost, examine the <a href="#_proposal_of_simple_contracts_by_consumer">solution</a>. To
create the second contract:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Set the <code>age</code> in the request to <code>17</code>.</p>
</li>
<li>
<p>Update the response body to return a <code>status</code> of <code>NOT_OK</code>.</p>
</li>
<li>
<p>Update the description.</p>
</li>
</ol>
</div>
</div>
<div class="sect3">
<h4 id="_defining_the_first_messaging_contract">Defining the First Messaging Contract</h4>
<div class="paragraph">
<p>We&#8217;ve done the case for HTTP. Let&#8217;s move to the
<code>src/main/resources/contracts/com/example/beer-api-producer-external/beer-api-consumer/messaging</code>
folder.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Time to define some contracts for messaging. Create a <code>shouldSendAcceptedVerification.groovy</code> file. If you&#8217;re lost just check out the <a href="#_proposal_of_simple_contracts_by_consumer">solution</a></p>
<div class="ulist">
<ul>
<li>
<p>Call the <code>org.springframework.cloud.contract.spec.Contract.make { }</code> method to start defining the contract</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
}</code></pre>
</div>
</div>
</li>
<li>
<p>You can call <code>description()</code> method to provide some meaningful description. TIP: You can use the
Groovy multiline String <code>""" """</code> to have all special characters escaped. Every new line in the String
will be converted into a new line character</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
}</code></pre>
</div>
</div>
</li>
<li>
<p>HTTP communication is synchronous - you send a request and you get a response. With messaging the situation
is different - a consumer suddenly might get a message. In the consumer tests the consumer needs a mean to
trigger that message. That hook is called a <code>label</code> in Spring Cloud Contract. Let&#8217;s call our label
<code>accepted_verification</code>. To define it in the contract just call the <code>label</code> method like this
<code>label 'accepted_verification'</code></p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    label "accepted_verification"
}</code></pre>
</div>
</div>
</li>
<li>
<p>Next we define the message that we would like to receive. So from the producer&#8217;s perspective that&#8217;s an
<code>outputMessage</code>. You can call that message in the Groovy DSL <code>outputMessage { }</code></p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    label "accepted_verification"
    outputMessage {

    }
}</code></pre>
</div>
</div>
</li>
<li>
<p>Inside that method we need to define where and what we want to send. Let&#8217;s start with the first.
You can call the <code>sentTo</code> method and provide the destination. According to the requirements we want
to send the message to the <code>verifications</code> channel. Let&#8217;s define that in the contract
by calling <code>sentTo 'verifications'</code></p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    label "accepted_verification"
    outputMessage {
        sentTo "verifications"
    }
}</code></pre>
</div>
</div>
</li>
<li>
<p>As for the body we just can call <code>body(eligible: true)</code>. That way we&#8217;ll send a JSON body via messaging</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    label "accepted_verification"
    outputMessage {
        sentTo "verifications"
        body(eligible: true)
    }
}</code></pre>
</div>
</div>
</li>
<li>
<p>We can also set headers on the message. Let&#8217;s call <code>headers { }</code> method and inside the closure we can set an
explicit header. In case of messaging with Spring Cloud Stream, a header that describes the content
type of the payload is called <code>contentType</code>. So we need to set it like this
<code>header("contentType", applicationJsonUtf8())</code>.</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    label "accepted_verification"
    outputMessage {
        sentTo "verifications"
        body(eligible: true)
        headers {
            header("contentType", applicationJsonUtf8())
        }
    }
}</code></pre>
</div>
</div>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>Congratulations! You have created your first messaging contract!</p>
</div>
</div>
<div class="sect3">
<h4 id="_defining_second_messaging_contract">Defining second messaging contract</h4>
<div class="paragraph">
<p>Now it&#8217;s time for you to create the second contract. Create a file called
<code>shouldSendRejectedVerification.groovy</code>.
If you get lost, examine the <a href="#_proposal_of_simple_contracts_by_consumer">solution</a>. To
define the second message contract;</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Set the <code>eligible</code> property in the response body to <code>false</code>.</p>
</li>
<li>
<p>Update the label to <code>rejected_verification</code>.</p>
</li>
<li>
<p>Update the description.</p>
</li>
</ol>
</div>
</div>
<div class="sect3">
<h4 id="_setting_up_spring_cloud_contract_in_the_producer_contracts_config_file_inside_the_contracts_repo">Setting up Spring Cloud Contract in the Producer Contracts Config File inside the Contracts Repo</h4>
<div class="paragraph">
<p>For a repository with contracts, we need a way for the consumer to convert the contracts
into stubs and install them locally. At the moment, the easiest way is to use of Maven or
Gradle. In this tutorial, we use Maven. You can see how the <code>pom.xml</code> should look in
<code>beer_contracts/example/pom.xml</code> and in the following example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;
	&lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;

	&lt;groupId&gt;com.example&lt;/groupId&gt;
	&lt;artifactId&gt;beer-api-producer-external&lt;/artifactId&gt;
	&lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;

	&lt;name&gt;Beer API producer Stubs&lt;/name&gt;
	&lt;description&gt;POM used to install locally stubs for consumer side&lt;/description&gt;

	&lt;parent&gt;
		&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
		&lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
		&lt;version&gt;2.4.0&lt;/version&gt;
		&lt;relativePath/&gt;
	&lt;/parent&gt;

	&lt;properties&gt;
		&lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;
		&lt;java.version&gt;1.8&lt;/java.version&gt;
		&lt;spring-cloud-contract.version&gt;2.4.0&lt;/spring-cloud-contract.version&gt;
		&lt;spring-cloud-dependencies.version&gt;2020.0.3-SNAPSHOT&lt;/spring-cloud-dependencies.version&gt;
		&lt;!-- We don't want to run tests --&gt;
		&lt;skipTests&gt;true&lt;/skipTests&gt;
		&lt;!-- We don't want to add build folders to the generated jar --&gt;
		&lt;excludeBuildFolders&gt;true&lt;/excludeBuildFolders&gt;
	&lt;/properties&gt;

	&lt;dependencyManagement&gt;
		&lt;dependencies&gt;
			&lt;dependency&gt;
				&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
				&lt;artifactId&gt;spring-cloud-dependencies&lt;/artifactId&gt;
				&lt;version&gt;${spring-cloud-dependencies.version}&lt;/version&gt;
				&lt;type&gt;pom&lt;/type&gt;
				&lt;scope&gt;import&lt;/scope&gt;
			&lt;/dependency&gt;
		&lt;/dependencies&gt;
	&lt;/dependencyManagement&gt;

	&lt;build&gt;
		&lt;plugins&gt;
			&lt;plugin&gt;
				&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
				&lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;
				&lt;version&gt;2.19.1&lt;/version&gt;
				&lt;configuration&gt;
					&lt;skipTests&gt;true&lt;/skipTests&gt;
				&lt;/configuration&gt;
			&lt;/plugin&gt;
			&lt;plugin&gt;
				&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
				&lt;artifactId&gt;spring-cloud-contract-maven-plugin&lt;/artifactId&gt;
				&lt;version&gt;${spring-cloud-contract.version}&lt;/version&gt;
				&lt;extensions&gt;true&lt;/extensions&gt;
				&lt;configuration&gt;
					&lt;!-- By default it would search under src/test/resources/ --&gt;
					&lt;contractsDirectory&gt;${project.basedir}&lt;/contractsDirectory&gt;
				&lt;/configuration&gt;
			&lt;/plugin&gt;
		&lt;/plugins&gt;
	&lt;/build&gt;
&lt;/project&gt;</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>This configuration file:</p>
<div class="ulist">
<ul>
<li>
<p>Sets the jar name to the <code>beer-api-producer-external</code> (that&#8217;s how the producer&#8217;s
called).</p>
</li>
<li>
<p>Disables test generation (we want only to generate stubs).</p>
</li>
<li>
<p>Adds the Spring Cloud Contract plugin (as you can see, there is no configuration
related to base classes).</p>
</li>
<li>
<p>Sets <code>excludeBuildFolders</code>, which is pretty descriptive. When generating stubs,
<code>target</code> and <code>build</code> folders are generated, and we don&#8217;t want them in the output jar.</p>
</li>
<li>
<p>Sets <code>contractsDirectory</code>. By default, Spring Cloud Contract searches under the
<code>src/test/resources/contracts</code> folder. In this case, we have the contracts under <code>/</code>
(from the point of view of the <code>pom.xml</code> file).</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>Now, as consumers, we want to convert the contracts into stubs so that we can use the
API. We use Maven to achieve that.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<div class="title">Important</div>
</td>
<td class="content">
You must have a standalone version of Maven installed!
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>+</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">$ mvn clean install</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now you have successfully installed the stubs locally.</p>
</div>
<div class="paragraph">
<p>You can check out the
<code>target/stubs/META-INF/com.example/beer-api-producer/0.0.1-SNAPSHOT</code> folder. In there,
you see the <code>contracts</code> folder, where all contracts were copied, and the <code>mappings</code>
folder, where you can find all the generated stubs. By default, Spring Cloud Contract
uses  <a href="http://wiremock.org">WireMock</a> as an implementation of fake HTTP server. Under the
<code>beer/rest</code> subfolder, you can see all the generated stubs. Notice that we use JSON Paths
to check the contents of the request.</p>
</div>
</div>
<div class="sect3">
<h4 id="_writing_the_missing_consumer_http_implementation">Writing the missing consumer HTTP implementation</h4>
<div class="ulist">
<ul>
<li>
<p>Let&#8217;s go back to our, consumer&#8217;s code - let&#8217;s go back to the <code>BeerControllerTest</code> and <code>BeerController</code>.
We know how we would like the API to look like so now we can write the missing implementation in the
<code>BeerController</code>. Let&#8217;s assume that the producer application will be running at
 <code><a href="http://localhost:8090/" class="bare">http://localhost:8090/</a></code>. Now go ahead and try to write the missing implementation
  of the <code>BeerController</code></p>
</li>
<li>
<p>In case of any issues you can check out the <a href="#_missing_consumer_controller_code">solution</a></p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_turning_on_stub_runner_in_http_consumer_tests">Turning on Stub Runner in HTTP consumer tests</h4>
<div class="ulist">
<ul>
<li>
<p>Let&#8217;s run the <code>BeerControllerTest</code> again. It will fail since we&#8217;re trying to send a request to
a real instance that hasn&#8217;t been started</p>
</li>
<li>
<p>Now it&#8217;s time to turn on the magic! Let&#8217;s add the Spring Cloud Starter Contract Stub Runner test dependency.</p>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
	&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
	&lt;artifactId&gt;spring-cloud-starter-contract-stub-runner&lt;/artifactId&gt;
	&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">testImplementation("org.springframework.cloud:spring-cloud-starter-contract-stub-runner")</code></pre>
</div>
</div>
</li>
<li>
<p>We can annotate our test class with
<code>@AutoConfigureStubRunner(stubsMode = StubRunnerProperties.StubsMode.LOCAL, ids = "com.example:beer-api-producer-external:+:stubs:8090")</code>. What that
will do is:</p>
<div class="ulist">
<ul>
<li>
<p>it will download the stub JARs from Maven local (<code>stubsMode = StubRunnerProperties.StubsMode.LOCAL</code>)</p>
</li>
<li>
<p>it will search for a JAR with coordinates <code>com.example:beer-api-producer-external</code> with latest version (<code>+</code>)
and <code>stubs</code> classifier. Once it&#8217;s found the fake HTTP server stub will be started at port <code>8090</code></p>
</li>
</ul>
</div>
</li>
<li>
<p>Rerun the test - it should automagically pass!</p>
<div class="ulist">
<ul>
<li>
<p>In the logs you will see information about downloading, unpacking and starting stubs (<a href="#_stub_logs">see the logs</a>)</p>
</li>
<li>
<p>What happened is that we could interact with real API without writing a single line of production code</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_playing_with_the_http_contracts">Playing with the HTTP contracts</h4>
<div class="ulist">
<ul>
<li>
<p>TDD is about red, green and refactor. We went through the first two. Time to refactor the code.
We come to the conclusion that the <code>name</code> field is unnecessary. In the <code>BeerController.java</code> file let&#8217;s
create a new class called <code>BeerRequest</code> that will contain only age field and let&#8217;s try to send that
to our stubbed producer. (<a href="#_beer_request">Show solution</a>)</p>
</li>
<li>
<p>Let&#8217;s run the tests again - what will happen is that the tests will fail. That&#8217;s because in the contract
you have explicitly described that you want the <code>name</code> to be there. As you can see all the typos will be
caught during the build time of your project.</p>
<div class="ulist">
<ul>
<li>
<p>The same will happen if you leave the <code>name</code> but change the <code>age</code> to some other value (e.g. 28).
Our stubs at the moment are very strict. We&#8217;ll try to fix that in a second</p>
</li>
</ul>
</div>
</li>
<li>
<p>To fix this you need to go back with your IDE to the producer and modify your HTTP contracts.</p>
<div class="ulist">
<ul>
<li>
<p>Just remove the <code>name</code> field from the request body.</p>
</li>
<li>
<p>Spring Cloud Contract allows you to provide dynamic values for parts of body, urls, headers etc.
This is especially useful when working with dates, database ids, UUIDs etc.</p>
</li>
<li>
<p>Let&#8217;s open the <code>shouldGrantABeerIfOldEnough.groovy</code> and go to the request body <code>age</code> element</p>
</li>
<li>
<p>Instead of <code>22</code> write <code>$(regex('[2-9][0-9]'))</code>. Now let&#8217;s analyze what this is.</p>
<div class="ulist">
<ul>
<li>
<p>In order to tell Spring Cloud Contract that there will be a dynamic value set you have to use either
the <code>$()</code> or <code>value()</code> method. They are equivalent.</p>
</li>
<li>
<p>Next we use <code>regex()</code> method that converts your <code>String</code> into <code>Pattern</code>. In this case we assume
a 2 digit number greater or equal to <code>20</code></p>
</li>
</ul>
</div>
</li>
<li>
<p>Repeat the same process for the <code>shouldRejectABeerIfTooYoung.groovy</code> contract but change the
regular expression to <code>[0-1][0-9]</code></p>
</li>
<li>
<p>Run the building with test skipping and check the output of stubs. You&#8217;ll see that the generated
mappings have changed from equality check in JSON Path to regular expression check</p>
</li>
<li>
<p>Go back to the consumer code and run the <code>BeerControlerTest</code> again. This time it should pass. You can
also change the values of age to e.g. <code>45</code> for the positive case and <code>11</code> for the negative on.</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_writing_the_missing_consumer_messaging_implementation">Writing the missing consumer messaging implementation</h4>
<div class="ulist">
<ul>
<li>
<p>We&#8217;ve gone through the HTTP scenario and now it&#8217;s time for the messaging part.</p>
</li>
<li>
<p>Let' start with a test as usual. Let&#8217;s check out the <code>BeerVerificationListenerTest</code> test class</p>
<div class="ulist">
<ul>
<li>
<p>there are 2 test methods with empty bodies</p>
</li>
<li>
<p>in both cases we need to trigger a message that will get sent to a destination at which our
listener class is awaiting messages</p>
</li>
<li>
<p>we&#8217;re missing the triggering part - but we&#8217;ll add it in a second</p>
</li>
</ul>
</div>
</li>
<li>
<p>On the consumer side let&#8217;s check out the <code>BeerVerificationListener</code> class.</p>
<div class="ulist">
<ul>
<li>
<p>We&#8217;re using the Spring Cloud Stream&#8217;s abstraction of a queue / topic which is called a <code>channel</code>.</p>
</li>
<li>
<p>There are 2 channels that come out od the box with SC-Stream. These are <code>input</code> and <code>output</code>.
Those channels can be found in 2 interfaces - <code>Sink</code> and <code>Source</code>. <code>Sink</code> contains the <code>input</code> channel
which is used for listening for messages and <code>Source</code> contains the <code>output</code> channel which
is used to send messages. In the listener class you can see that we use the <code>Sink</code> one cause we&#8217;re waiting for
a message to be received.</p>
</li>
<li>
<p>We have to configure the <code>destination</code>, so the actual name of a queue / topic on which we will be
listening. To do that you have to set in the <code>src/main/resources/application.yml</code> the property
<code>spring.cloud.stream.bindings.input-in-0.destination: verifications</code>. That means that the we&#8217;ll use the
<code>input</code> channel (so the channel in the <code>Sink</code> interface) to listen to messages coming from a
destination called <code>verifications</code>.</p>
</li>
<li>
<p>Now that we have configured Spring Cloud Stream let&#8217;s write the missing feature. If the <code>eligible</code> flag
in the incoming message is <code>true</code> - increase the <code>eligibleCounter</code> value. Otherwise increment the
other <code>notEligibleCounter</code> one. (<a href="#_missing_listener_code">Show solution</a>)</p>
</li>
</ul>
</div>
</li>
<li>
<p>Now that the implementation is written - let&#8217;s try to run our <code>BeerVerificationListenerTest</code> tests.
Unfortunately they will fail cause no message has been received - we&#8217;ll still missing that part</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_turning_on_stub_runner_in_messaging_consumer_tests">Turning on Stub Runner in messaging consumer tests</h4>
<div class="ulist">
<ul>
<li>
<p>Time to use Spring Cloud Contract!</p>
<div class="ulist">
<ul>
<li>
<p>We need to use Spring Cloud Contract Stub Runner so that it downloads the stubs. Just add the
<code>@AutoConfigureStubRunner(stubsMode = StubRunnerProperties.StubsMode.LOCAL, ids = "com.example:beer-api-producer-external")</code> to download
the latest stubs of <code>com.example:beer-api-producer-external</code>, with classifier <code>stubs</code> and if the JAR
contains any HTTP stubs then register them at a random port.</p>
</li>
<li>
<p>Now we need a solution to trigger the message. To do that we need to autowire a <code>StubTrigger</code> interface.
Just add <code>@Autowired StubTrigger stubTrigger</code> field to your test</p>
</li>
<li>
<p>In the contract on the producer side we&#8217;ve described 2 labels. <code>accepted_verification</code> and <code>rejected_verification</code>.
You can use the <code>StubTrigger#trigger</code> method to trigger a message with a given label. For example
if you call <code>stubTrigger.trigger("accepted_verification")</code> you&#8217;ll trigger a message that got described
with the <code>accepted_verification</code> label.</p>
</li>
<li>
<p>Now add the missing <code>StubTrigger#tigger</code> method in the test bodies. (<a href="#_missing_triggers">Show solution</a>)</p>
</li>
<li>
<p>Run the tests and they should pass!</p>
</li>
<li>
<p>You can change the <code>destination</code> name in <code>src/main/resources/application.yml</code> to <code>foo</code> and rerun the
tests - you&#8217;ll see that they&#8217;ll start failing. That&#8217;s because you&#8217;re listening to messages
at destination <code>foo</code> whereas the message is sent to <code>verifications</code></p>
</li>
<li>
<p>You can also play around with the <code>Verification</code> payload class. If you change the field name from
<code>eligible</code> to <code>foo</code> an rerun the tests - the tests will fail. If you change the type from <code>boolean</code>
to <code>Integer</code> (and change the production code too) then the tests will fail due to serialization problems</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>Congratulations! As a consumer, you successfully used the API of the producer for both
HTTP and messaging. Now you can file a pull request (PR) to the repository that stores
all contracts.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_producer_flow_1">Producer Flow 1</h3>
<div class="imageblock">
<div class="content">
<img src="../images/external_producer_flow_1.png" alt="external producer flow 1">
</div>
<div class="title">Figure 7. Producer takes over the PR filed to the repo with contracts, writes missing impl on the producer side</div>
</div>
<div class="sect3">
<h4 id="_ide_setup_2">IDE setup</h4>
<div class="paragraph">
<p>Open <code>producer_with_external_contracts</code> project (either via Maven or Gradle) in your IDE.</p>
</div>
<div class="paragraph">
<p>This tutorial assumes that you have taken over the PR of the <code>beer_contracts</code>. The
following git commands show an example of how to do so for a PR that got submitted to via
a branch called <code>the_pr</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">git fetch origin
git checkout -b the_pr origin/the_pr
git merge master</code></pre>
</div>
</div>
<div class="paragraph">
<p>The core idea of Spring Cloud Contract is stub and contract validity. Right now, you have
a set of contracts defined but haven&#8217;t tested it against the producer side. It&#8217;s time to
change that!</p>
</div>
</div>
<div class="sect3">
<h4 id="_install_the_contracts_locally">Install the Contracts Locally</h4>
<div class="paragraph">
<p>In order for the producer to use the contracts, we need to produce a JAR with all the
contracts. To achieve that, use Maven&#8217;s assembly plugin. You can find the configuration
under <code>beer_contracts/src/assembly/contracts.xml</code>. We still need to configure the
<code>beer_contracts/pom.xml</code> by providing the assembly plugin configuration.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;plugin&gt;
  &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
  &lt;artifactId&gt;maven-assembly-plugin&lt;/artifactId&gt;
  &lt;executions&gt;
      &lt;execution&gt;
          &lt;id&gt;contracts&lt;/id&gt;
          &lt;phase&gt;prepare-package&lt;/phase&gt;
          &lt;goals&gt;
              &lt;goal&gt;single&lt;/goal&gt;
          &lt;/goals&gt;
          &lt;configuration&gt;
              &lt;attach&gt;true&lt;/attach&gt;
              &lt;descriptor&gt;${basedir}/src/assembly/contracts.xml&lt;/descriptor&gt;
              &lt;appendAssemblyId&gt;false&lt;/appendAssemblyId&gt;
          &lt;/configuration&gt;
      &lt;/execution&gt;
  &lt;/executions&gt;
&lt;/plugin&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The preceding snippet creates a <code>beer-contracts</code> JAR (in the <code>target</code> folder) that
contains all contracts and poms from <code>src/main/resources/contracts</code>.</p>
</div>
</div>
<div class="sect3">
<h4 id="_setting_up_the_spring_cloud_contract_dependencies_on_the_producer_side">Setting up the Spring Cloud Contract Dependencies on the Producer Side</h4>
<div class="paragraph">
<p>First, let&#8217;s add the Spring Cloud Contract Verifier dependency to the project, as shown
in the following snippet:</p>
</div>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
	&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
	&lt;artifactId&gt;spring-cloud-starter-contract-verifier&lt;/artifactId&gt;
	&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">testImplementation("org.springframework.cloud:spring-cloud-starter-contract-verifier")</code></pre>
</div>
</div>
<div class="paragraph">
<p>Spring Cloud Contract can generate tests from your contracts to ensure that your
implementation&#8217;s API is compatible with the defined contract. Let&#8217;s set up the project to
start generating tests.</p>
</div>
<div class="paragraph">
<p>Spring Cloud Contract needs a base class that all of the generated tests will extend.
Currently, we support three different ways of defining a base class (you can read more
about this in the Spring Cloud Contract documentation for
<a href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_configure_plugin">Gradle</a>
and <a href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_configure_plugin_2">Maven</a>).</p>
</div>
<div class="ulist">
<ul>
<li>
<p>A single class for all tests.</p>
</li>
<li>
<p>Convention-based naming (which takes the last two package names and appends <code>Base</code>. For
example, a contract <code>src/test/resources/contracts/foo/bar/shouldDoSth.groovy</code> creates a
test class called <code>BarTest</code> that would extend the <code>FooBarBase</code> class.</p>
</li>
<li>
<p>Manual mapping (you can state that contracts matching certain regular expressions must
have a base class with fully qualified name equal to the value you specify).</p>
</li>
</ul>
</div>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;plugin&gt;
    &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
    &lt;artifactId&gt;spring-cloud-contract-maven-plugin&lt;/artifactId&gt;
    &lt;version&gt;${spring-cloud-contract.version}&lt;/version&gt;
    &lt;extensions&gt;true&lt;/extensions&gt;
    &lt;configuration&gt;
        &lt;baseClassMappings&gt;
            &lt;baseClassMapping&gt;
                &lt;contractPackageRegex&gt;.*messaging.*&lt;/contractPackageRegex&gt;
                &lt;baseClassFQN&gt;com.example.BeerMessagingBase&lt;/baseClassFQN&gt;
            &lt;/baseClassMapping&gt;
            &lt;baseClassMapping&gt;
                &lt;contractPackageRegex&gt;.*rest.*&lt;/contractPackageRegex&gt;
                &lt;baseClassFQN&gt;com.example.BeerRestBase&lt;/baseClassFQN&gt;
            &lt;/baseClassMapping&gt;
        &lt;/baseClassMappings&gt;
        &lt;!-- We want to use the JAR with contracts with the following coordinates --&gt;
        &lt;contractDependency&gt;
            &lt;groupId&gt;com.example&lt;/groupId&gt;
            &lt;artifactId&gt;beer-contracts&lt;/artifactId&gt;
        &lt;/contractDependency&gt;
        &lt;!-- The JAR with contracts should be taken from Maven local --&gt;
        &lt;contractsMode&gt;LOCAL&lt;/contractsMode&gt;
        &lt;!-- Base package for generated tests --&gt;
        &lt;basePackageForTests&gt;com.example&lt;/basePackageForTests&gt;
    &lt;/configuration&gt;
    &lt;!-- this was added for testing purposes only --&gt;
    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
            &lt;artifactId&gt;spring-cloud-contract-verifier&lt;/artifactId&gt;
            &lt;version&gt;${spring-cloud-contract.version}&lt;/version&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;
&lt;/plugin&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">contracts {
	testFramework = "JUNIT5"
	// We want to use the JAR with contracts with the following coordinates
	contractDependency {
		stringNotation = 'com.example:beer-contracts'
	}
	// The JAR with contracts should be taken from Maven local
	contractsMode = "LOCAL"
	// Base package for generated tests
	basePackageForTests = "com.example"
	baseClassMappings {
		baseClassMapping(".*messaging.*", "com.example.BeerMessagingBase")
		baseClassMapping(".*rest.*", "com.example.BeerRestBase")
	}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>In both cases, we define that we want to download the JAR with contracts with given
coordinates (<code>com.example:beer-contracts</code>).</p>
</div>
<div class="paragraph">
<p>We do not provide the <code>contractsRepositoryUrl</code> (the URL from which we expect the
contracts to be downloaded), because we want to work offline. That&#8217;s why we set the
<code>LOCAL</code> mode.</p>
</div>
<div class="paragraph">
<p>We decided that all the generated tests should be generated under the <code>com.example</code>
package instead of the default one.</p>
</div>
<div class="paragraph">
<p>We have manually set mappings of packages in which contracts are stored to a fully
qualified name of the base class. If there&#8217;s a contract that has a <code>messaging</code> package
name in its path, it will be mapped to a <code>com.example.BeerMessagingBase</code> base class.</p>
</div>
</div>
<div class="sect3">
<h4 id="_updating_contracts_from_the_pull_request">Updating Contracts from the Pull Request</h4>
<div class="ulist">
<ul>
<li>
<p>We need to modify the messaging contracts cause they are missing one important piece from the
producer&#8217;s perspective - the <code>input</code> part</p>
<div class="ulist">
<ul>
<li>
<p>In case of messaging there has to be some trigger that will result in producing an output message</p>
</li>
<li>
<p>Spring Cloud Contract accepts 3 situations</p>
<div class="ulist">
<ul>
<li>
<p>Input message produces an output message</p>
</li>
<li>
<p>A method execution produces an output message</p>
</li>
<li>
<p>Input message doesn&#8217;t produce any output message</p>
</li>
</ul>
</div>
</li>
<li>
<p>In our situation we&#8217;ll have a method produce an output. It&#8217;s enough to pass the <code>input {}</code> method
and then the <code>triggeredBy</code> method. The <code>triggeredBy</code> method requires a String with a method execution.
So if in the base class we expect to have a method called <code>triggerSomeMessage()</code> that would trigger a message
for tests, then we would write <code>input { triggeredBy("triggerSomeMessage()") }</code> to make this happen. Example:</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    label "accepted_verification"
    input {
        triggeredBy("triggerSomeMessage()")
    }
    outputMessage {
        sentTo "verifications"
        body(eligible: true)
        headers {
            header("contentType", applicationJsonUtf8())
        }
    }
}</code></pre>
</div>
</div>
</li>
<li>
<p>For this workshop for the <code>shouldSendAcceptedVerification.groovy</code> we want to trigger the <code>clientIsOldEnough()</code>
    method and for <code>shouldSendRejectedVerification.groovy</code> we want to trigger the <code>clientIsTooYoung()</code> method
from the base class. (<a href="#_messaging_dsls">Show solution</a>)</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<div class="title">Important</div>
</td>
<td class="content">
Remember to rebuild the JAR with contracts in the <code>beer_contracts</code> repo. You
need to produce and install the JAR in your Maven local.
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="_generating_tests_from_contracts">Generating tests from contracts</h4>
<div class="ulist">
<ul>
<li>
<p>Let&#8217;s generate the tests! Just call:</p>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">$ ./mvnw clean install</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">$ ./gradlew clean build publishToMavenLocal</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>Suddenly some tests should start failing. Those tests are the autogenerated tests created
by Spring Cloud Contract</p>
</li>
<li>
<p>The tests lay under <code>/generated-test-sources/contracts/org/springframework/cloud/contract/verifier/tests/beer</code>
in <code>target</code> for Maven or <code>build</code> for Gradle</p>
</li>
<li>
<p>There will be a test for each folder in which you store your contracts. The name of the test class
will be the name of that folder</p>
</li>
<li>
<p>Each of the contracts will be a single test inside that test class</p>
</li>
<li>
<p>If you check out the generated tests you&#8217;ll notice that the dynamic parts of the <code>request</code> part
of the contract got converted to a concrete value. Any dynamic bits on the <code>response</code> side would be
converted into matchers.</p>
</li>
</ul>
</div>
</li>
<li>
<p>Time to fix the broken tests. We need to do that by providing the missing implementation.</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_fixing_broken_http_tests">Fixing broken HTTP tests</h4>
<div class="ulist">
<ul>
<li>
<p>Let&#8217;s start with HTTP</p>
<div class="ulist">
<ul>
<li>
<p>First let&#8217;s write the missing implementation in <code>ProducerController</code>. The logic to be written
is extremely simple - if the <code>personCheckingService.shouldGetBeer(&#8230;&#8203;)</code> returns <code>true</code> then we
should return <code>new Response(BeerCheckStatus.OK)</code>. Otherwise <code>new Response(BeerCheckStatus.NOT_OK)</code>.
(<a href="#_producerController_implementation">Show solution</a>)</p>
</li>
</ul>
</div>
</li>
<li>
<p>Let&#8217;s fix the <code>BeerRestBase</code> class now</p>
<div class="ulist">
<ul>
<li>
<p>The idea of CDC is <strong>NOT TO TEST</strong> every single feature. Contract tests are there to see if the API
is matched, <strong>NOT</strong> that the feature is working. That&#8217;s why we shouldn&#8217;t be accessing databases etc.
That means that we will work with mock of the <code>PersonCheckingService</code>. (<a href="#_beerrestbase">Show solution</a>)</p>
</li>
<li>
<p>Let&#8217;s annotate the test class with <code>@RunWith(MockitoJUnitRunner.class)</code> to enable Mockito runner.</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(MockitoJUnitRunner.class)
public abstract class BeerRestBase {
...
}</code></pre>
</div>
</div>
</li>
<li>
<p>We&#8217;ll want to test the <code>ProducerController</code> so we can create a field <code>@InjectMocks ProducerController
producerController</code>. Mockito will inject any mocks for us via the constructor.</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">    @Mock PersonCheckingService personCheckingService;
    @InjectMocks ProducerController producerController;

    @BeforeEach
    public void setup() {
        given(personCheckingService.shouldGetBeer(argThat(oldEnough()))).willReturn(true);
    }</code></pre>
</div>
</div>
</li>
<li>
<p>It won&#8217;t compile cause we don&#8217;t have the <code>oldEnough()</code> method but don&#8217;t worry. So this line stubs
the <code>shouldGetBeer</code> method in such a way that if the user is old enough then the method will return
true. Let&#8217;s now add the <code>oldEnoughMethod()</code></p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">	private TypeSafeMatcher&lt;PersonToCheck&gt; oldEnough() {
		return new TypeSafeMatcher&lt;PersonToCheck&gt;() {
			@Override protected boolean matchesSafely(PersonToCheck personToCheck) {
				return personToCheck.age &gt;= 20;
			}
			@Override public void describeTo(Description description) {
			}
		};
	}</code></pre>
</div>
</div>
</li>
<li>
<p>We&#8217;re using the <code>TypeSafeMatcher</code> from Hamcrest to create a matcher for <code>PersonToCheck</code>. In this case
if the person to check is older or is 20 then the method <code>shouldGetBeer</code> method will return <code>true</code>.</p>
</li>
<li>
<p>Now we need to configure <a href="http://rest-assured.io/">RestAssured</a> that is used by Spring Cloud Contract
to send requests. In our case we want to profit from MockMvc. In order to set the <code>ProducerController</code>
with RestAssured it&#8217;s enough to call <code>
		// https://github.com/spring-cloud/spring-cloud-contract/issues/1428
		EncoderConfig encoderConfig = new EncoderConfig().appendDefaultContentCharsetToContentTypeIfUndefined(false);
		RestAssuredMockMvc.config = new RestAssuredMockMvcConfig().encoderConfig(encoderConfig);
		RestAssuredMockMvc.standaloneSetup(producerController);</code></p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(MockitoJUnitRunner.class)
public abstract class BeerRestBase {

    @Mock PersonCheckingService personCheckingService;
    @InjectMocks ProducerController producerController;

    @BeforeEach
    public void setup() {
        given(personCheckingService.shouldGetBeer(argThat(oldEnough()))).willReturn(true);

		// https://github.com/spring-cloud/spring-cloud-contract/issues/1428
		EncoderConfig encoderConfig = new EncoderConfig().appendDefaultContentCharsetToContentTypeIfUndefined(false);
		RestAssuredMockMvc.config = new RestAssuredMockMvcConfig().encoderConfig(encoderConfig);
		RestAssuredMockMvc.standaloneSetup(producerController);
    }

    private TypeSafeMatcher&lt;PersonToCheck&gt; oldEnough() {
        return new TypeSafeMatcher&lt;PersonToCheck&gt;() {
            @Override protected boolean matchesSafely(PersonToCheck personToCheck) {
                return personToCheck.age &gt;= 20;
            }
            @Override public void describeTo(Description description) {
            }
        };
    }
}</code></pre>
</div>
</div>
</li>
<li>
<p>With mocks and RestAssured setup - we&#8217;re ready to run our HTTP based autogenerated tests</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_fixing_broken_messaging_tests">Fixing broken messaging tests</h4>
<div class="ulist">
<ul>
<li>
<p>Now let&#8217;s go to the messaging part.</p>
</li>
<li>
<p>Let&#8217;s check out the <code>src/main/resources/application.yml</code> file whether it contains the proper
destination set for <code>spring.cloud.stream.bindings.output.destination</code>. If not then let&#8217;s set it
to <code>verifications</code> - this is the queue / topic we&#8217;d like to receive the message from</p>
</li>
<li>
<p>We&#8217;re trying to do TDD so let&#8217;s move to <code>BeerMessagingBase</code> test class. The first thing we need to do is to
add the <code>@AutoConfigureMessageVerifier</code> annotation on the test class. That will configure
the setup related to messaging and Spring Cloud Contract.</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(SpringRunner.class)
@SpringBootTest(classes = ProducerApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
@AutoConfigureMessageVerifier
@ImportAutoConfiguration(TestChannelBinderConfiguration.class)
public abstract class BeerMessagingBase {
...
}</code></pre>
</div>
</div>
</li>
<li>
<p>We need to prepare some setup for our tests. To do that we&#8217;ll need to clear any remaining
messages that could break our tests. To do that we&#8217;ll use the Spring Cloud Contract <code>MessageVerifier</code>
abstraction (it allows to send and receive messages from e.g. Spring Cloud Stream, Sprig Integration, Apache Camel.)</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(SpringRunner.class)
@SpringBootTest(classes = ProducerApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
@AutoConfigureMessageVerifier
@ImportAutoConfiguration(TestChannelBinderConfiguration.class)
public abstract class BeerMessagingBase {
    @Inject MessageVerifier messaging;
	@Autowired PersonCheckingService personCheckingService;

	@BeforeEach
	public void setup() {
		// let's clear any remaining messages
		// output == destination or channel name
		this.messaging.receive("output", 100, TimeUnit.MILLISECONDS);
	}

	public void clientIsOldEnough() {
    }

    public void clientIsTooYoung() {
    }
}</code></pre>
</div>
</div>
</li>
<li>
<p>In the <code>clientIsOldEnough()</code> and <code>clientIsTooYoung()</code> we need the logic to trigger a message.
What triggers a message will be the implementation of the <code>PersonCheckingService#shouldGetBeer</code>.</p>
</li>
<li>
<p>For <code>clientIsOldEnough()</code> we can use a <code>PersonToCheck</code> of age <code>25</code> for example and
<code>clientIsTooYoung</code> can have age <code>5</code>. (<a href="#_beermessagingbase">Show solution</a>)</p>
</li>
<li>
<p>We can run the test which will obviously fail because we have a missing implementation. Let&#8217;s move
to <code>AgeCheckingPersonCheckingService</code></p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_writing_the_missing_producer_messaging_implementation">Writing the missing producer messaging implementation</h4>
<div class="ulist">
<ul>
<li>
<p>We need to check if the person&#8217;s age is greater or equal to 20 - if that&#8217;s the case then the
we need to send the properly generated <code>Verification</code> object. In order to send a message you can use the
following code <code>source.output().send(MessageBuilder.withPayload(new Verification(true)).build())</code>.
In this case we&#8217;re sending a message to the <code>output</code> channel (that is bound to <code>verifications</code> destination).
(<a href="#_messaging_implementation">Show solution</a>)</p>
</li>
<li>
<p>Let&#8217;s run the tests again - they should all pass!</p>
</li>
<li>
<p>Now let&#8217;s ensure that we can successfully publish artifacts to Maven local</p>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">$ ./mvnw clean install</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">$ ./gradlew clean build publishToMavenLocal</code></pre>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_producer_flow_2">Producer Flow 2</h3>
<div class="imageblock">
<div class="content">
<img src="../images/external_producer_flow_2.png" alt="external producer flow 2">
</div>
<div class="title">Figure 8. Once done the producer merges the PR to the repo with contracts. The CI system will produce a JAR with all contracts</div>
</div>
<div class="ulist">
<ul>
<li>
<p>Now you would merge the PR from <code>beer_contracts</code> repo to master and your CI system would build a fat jar and stubs</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_producer_flow_3">Producer Flow 3</h3>
<div class="imageblock">
<div class="content">
<img src="../images/external_producer_flow_3.png" alt="external producer flow 3">
</div>
<div class="title">Figure 9. Once the PR got merged, the CI built the JAR of the contracts repo then the producer&#8217;s code can use that JAR in its own building process</div>
</div>
<div class="paragraph">
<p>After the pull request gets merged and the <code>beer-contracts</code> artifact gets published, you
need to switch off your offline work in the Spring Cloud Contract (we do not do so for
this tutorial). In a "real life" situation you would need to update it as shown in the
following snippet:</p>
</div>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;plugin&gt;
    &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
    &lt;artifactId&gt;spring-cloud-contract-maven-plugin&lt;/artifactId&gt;
    &lt;version&gt;${spring-cloud-contract.version}&lt;/version&gt;
    &lt;extensions&gt;true&lt;/extensions&gt;
    &lt;configuration&gt;
        &lt;baseClassMappings&gt;
            &lt;baseClassMapping&gt;
                &lt;contractPackageRegex&gt;.*messaging.*&lt;/contractPackageRegex&gt;
                &lt;baseClassFQN&gt;com.example.BeerMessagingBase&lt;/baseClassFQN&gt;
            &lt;/baseClassMapping&gt;
            &lt;baseClassMapping&gt;
                &lt;contractPackageRegex&gt;.*rest.*&lt;/contractPackageRegex&gt;
                &lt;baseClassFQN&gt;com.example.BeerRestBase&lt;/baseClassFQN&gt;
            &lt;/baseClassMapping&gt;
        &lt;/baseClassMappings&gt;
        &lt;!-- We want to use the JAR with contracts with the following coordinates --&gt;
        &lt;contractDependency&gt;
            &lt;groupId&gt;com.example&lt;/groupId&gt;
            &lt;artifactId&gt;beer-contracts&lt;/artifactId&gt;
        &lt;/contractDependency&gt;
        &lt;!-- The JAR with contracts will get downloaded from an external repo --&gt;
        &lt;contractsRepositoryUrl&gt;https://foo.bar/baz&lt;/contractsRepositoryUrl&gt;
        &lt;!-- Base package for generated tests --&gt;
        &lt;basePackageForTests&gt;com.example&lt;/basePackageForTests&gt;
    &lt;/configuration&gt;
&lt;/plugin&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>+</p>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">contracts {
	testFramework = "JUNIT5"
	// We want to use the JAR with contracts with the following coordinates
	contractDependency {
		stringNotation = 'com.example:beer-contracts'
	}
	// The JAR with contracts will get downloaded from an external repo
	contracts {
	testFramework = "JUNIT5"
		repositoryUrl = "https://foo.bar/baz"
	}
	// Base package for generated tests
	basePackageForTests = "com.example"
	baseClassMappings {
		baseClassMapping(".*messaging.*", "com.example.BeerMessagingBase")
		baseClassMapping(".*rest.*", "com.example.BeerRestBase")
	}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Congratulations! you&#8217;ve completed the producer side of this tutorial!</p>
</div>
</div>
<div class="sect2">
<h3 id="_consumer_flow_2">Consumer flow 2</h3>
<div class="imageblock">
<div class="content">
<img src="../images/consumer_flow_2.png" alt="consumer flow 2">
</div>
<div class="title">Figure 10. Switch to work online</div>
</div>
<div class="ulist">
<ul>
<li>
<p>After merging the PR the producer&#8217;s stubs reside in some Artifactory / Nexus instance</p>
</li>
<li>
<p>As consumers we no longer want to retrieve the stubs from our local Maven repository -
we&#8217;d like to download them from the remote location</p>
</li>
<li>
<p>To do that (we won&#8217;t do that for the tutorial but you would do it in your "production"
code) it&#8217;s enough to pass the <code>repositoryRoot</code> parameter and set the
<code>stubsMode</code> to <code>StubRunnerProperties.StubsMode.REMOTE</code></p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
@AutoConfigureMockMvc
@AutoConfigureJsonTesters
@AutoConfigureStubRunner(
repositoryRoot="http://www.foo.com/bar,
ids = "com.example:beer-api-producer-external:+:stubs:8090",
stubsMode = StubRunnerProperties.StubsMode.REMOTE
)
@DirtiesContext
public class YourTestOnTheConsumerSide extends AbstractTest {
}</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>Another option is to pass the property <code>stubrunner.repositoryRoot</code> either as a
system / environment property, or via an <code>application.yml</code> and <code>stubrunner.stubs-mode</code>
equal to <code>remote</code></p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_generating_documentation_from_contracts">Generating documentation from contracts</h3>
<div class="paragraph">
<p>Another feature of Spring Cloud Contract is an option to easily create the documentation
of the whole API of the producer. You can create the following test that will generate a
<code>contracts.adoc</code> file under <code>target/generated-snippets/</code> with description of contracts and
with the contract bodies as such.</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
This test is a poor man&#8217;s version of the documentation generation. You can customize
it as you wish - the current version is just to show you an example.
</td>
</tr>
</table>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">package docs;

import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.contract.spec.Contract;
import org.springframework.cloud.contract.verifier.util.ContractVerifierDslConverter;
import org.springframework.core.io.Resource;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collection;
import java.util.regex.Pattern;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;

@SpringJUnitConfig
public class GenerateAdocsFromContractsTests {

	// TODO: Can be parametrized
	@Value("classpath:contracts") Resource contracts;
	private static String header = "= Application Contracts\n" + "\n"
			+ "In the following document you'll be able to see all the contracts that are present for this application.\n"
			+ "\n" + "== Contracts\n";

	@Test public void should_convert_contracts_into_adoc() throws IOException {
		final StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append(header);
		final Path rootDir = this.contracts.getFile().toPath();

		Files.walkFileTree(rootDir, new FileVisitor&lt;Path&gt;() {
			private Pattern pattern = Pattern.compile("^.*groovy$");

			@Override
			public FileVisitResult preVisitDirectory(Path path, BasicFileAttributes atts)
					throws IOException {
				return FileVisitResult.CONTINUE;
			}

			@Override
			public FileVisitResult visitFile(Path path, BasicFileAttributes mainAtts)
					throws IOException {
				boolean matches = this.pattern.matcher(path.toString()).matches();
				if (matches) {
					appendContract(stringBuilder, path);
				}
				return FileVisitResult.CONTINUE;
			}

			@Override
			public FileVisitResult postVisitDirectory(Path path, IOException exc)
					throws IOException {
				return FileVisitResult.CONTINUE;
			}

			@Override public FileVisitResult visitFileFailed(Path path, IOException exc)
					throws IOException {
				// If the root directory has failed it makes no sense to continue
				return path.equals(rootDir) ?
						FileVisitResult.TERMINATE :
						FileVisitResult.CONTINUE;
			}
		});

		//String outputAdoc = asciidoctor.convert(stringBuilder.toString(), new HashMap&lt;String, Object&gt;());
		String outputAdoc = stringBuilder.toString();
		// TODO: Can be parametrized
		File outputDir = new File("target/generated-snippets");
		outputDir.mkdirs();
		// TODO: Can be parametrized
		File outputFile = new File(outputDir, "contracts.adoc");
		if (outputFile.exists()) {
			outputFile.delete();
		}
		if (outputFile.createNewFile()) {
			Files.write(outputFile.toPath(), outputAdoc.getBytes());
		}
	}

	static StringBuilder appendContract(final StringBuilder stringBuilder, Path path)
			throws IOException {
		Collection&lt;Contract&gt; contracts = ContractVerifierDslConverter.convertAsCollection(path.getParent().toFile(), path.toFile());
		// TODO: Can be parametrized
		contracts.forEach(contract -&gt; {
			stringBuilder.append("### ")
					.append(path.getFileName().toString())
					.append("\n\n")
					.append(contract.getDescription())
					.append("\n\n")
					.append("#### Contract structure")
					.append("\n\n")
					.append("[source,java,indent=0]")
					.append("\n")
					.append("----")
					.append("\n")
					.append(fileAsString(path))
					.append("\n")
					.append("----")
					.append("\n\n");
		});
		return stringBuilder;
	}

	static String fileAsString(Path path) {
		try {
			byte[] encoded = Files.readAllBytes(path);
			return new String(encoded, StandardCharsets.UTF_8);
		}
		catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_solutions">Solutions</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_written_consumer_tests">Written consumer tests</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">	@Test
	public void should_give_me_a_beer_when_im_old_enough() throws Exception {
		//remove::start[]
		this.mockMvc.perform(MockMvcRequestBuilders.post("/beer")
				.contentType(MediaType.APPLICATION_JSON)
				.content(this.json.write(new Person("marcin", 22)).getJson()))
				.andExpect(status().isOk())
				.andExpect(content().string("THERE YOU GO"));
		//remove::end[]
	}

	@Test
	public void should_reject_a_beer_when_im_too_young() throws Exception {
		//remove::start[]
		this.mockMvc.perform(MockMvcRequestBuilders.post("/beer")
				.contentType(MediaType.APPLICATION_JSON)
				.content(this.json.write(new Person("marcin", 17)).getJson()))
				.andExpect(status().isOk())
				.andExpect(content().string("GET LOST"));
		//remove::end[]
	}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_adding_spring_cloud_contract_dependency">Adding Spring Cloud Contract Dependency</h3>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
	&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
	&lt;artifactId&gt;spring-cloud-starter-contract-verifier&lt;/artifactId&gt;
	&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">testImplementation("org.springframework.cloud:spring-cloud-starter-contract-verifier")</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_proposal_of_simple_contracts_by_consumer">Proposal of simple contracts by consumer</h3>
<div class="paragraph">
<p><strong>HTTP communication</strong></p>
</div>
<div class="listingblock primary">
<div class="title">Old Enough</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// rest/shouldGrantABeerIfOldEnough.groovy
org.springframework.cloud.contract.spec.Contract.make {
		description("""
Represents a successful scenario of getting a beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll grant him the beer
```

""")
	request {
		method 'POST'
		url '/check'
		body(
				age: 22,
				name: "marcin"
		)
		headers {
			contentType(applicationJson())
		}
	}
	response {
		status 200
		body("""
			{
				"status": "OK"
			}
			""")
		headers {
			contentType(applicationJson())
		}
	}
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Too Young</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// rest/shouldRejectABeerIfTooYoung.groovy
org.springframework.cloud.contract.spec.Contract.make {
		description("""
Represents a successful scenario of getting a beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll grant him the beer
```

""")
	request {
		method 'POST'
		url '/check'
		body(
				age: 17,
				name: "marcin"
		)
		headers {
			contentType(applicationJson())
		}
	}
	response {
		status 200
		body("""
			{
				"status": "NOT_OK"
			}
			""")
		headers {
			contentType(applicationJson())
		}
	}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p><strong>Messaging communication</strong></p>
</div>
<div class="listingblock primary">
<div class="title">Positive Verification</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// messaging/shouldSendAcceptedVerification.groovy
org.springframework.cloud.contract.spec.Contract.make {
	description("""
Sends a positive verification message when person is eligible to get the beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll send a message with a positive verification
```

""")
	// Label by means of which the output message can be triggered
	label 'accepted_verification'
	// output message of the contract
	outputMessage {
		// destination to which the output message will be sent
		sentTo 'verifications'
		// the body of the output message
		body(
            eligible: true
		)
		headers {
			header("contentType", applicationJsonUtf8())
		}
	}
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Negative Verification</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// messaging/shouldSendRejectedVerification.groovy
org.springframework.cloud.contract.spec.Contract.make {
	description("""
Sends a negative verification message when person is not eligible to get the beer

```
given:
	client is too young
when:
	he applies for a beer
then:
	we'll send a message with a negative verification
```

""")
	// Label by means of which the output message can be triggered
	label 'rejected_verification'
	// output message of the contract
	outputMessage {
		// destination to which the output message will be sent
		sentTo 'verifications'
		// the body of the output message
		body(
            eligible: false
		)
		headers {
			header("contentType", applicationJsonUtf8())
		}
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_missing_consumer_controller_code">Missing consumer controller code</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">		ResponseEntity&lt;Response&gt; response = this.restTemplate.exchange(
				RequestEntity
						.post(URI.create("http://localhost:" + this.port + "/check"))
						.contentType(MediaType.APPLICATION_JSON)
						.body(person),
				Response.class);
		switch (response.getBody().status) {
		case OK:
			return "THERE YOU GO";
		default:
			return "GET LOST";
		}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_stub_logs">Stub Logs</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">2017-05-11 12:16:51.146  INFO 4693 --- [           main] o.s.c.c.s.StubDownloaderBuilderProvider  : Will download stubs using Aether
2017-05-11 12:16:51.148  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Remote repos not passed but the switch to work offline was set. Stubs will be used from your local Maven repository.
2017-05-11 12:16:51.291  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Desired version is [+] - will try to resolve the latest version
2017-05-11 12:16:51.308  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolved version is [0.0.1-SNAPSHOT]
2017-05-11 12:16:51.309  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolving artifact [com.example:{producer_artifact}:jar:stubs:0.0.1-SNAPSHOT] using remote repositories []
2017-05-11 12:16:51.317  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolved artifact [com.example:{producer_artifact}:jar:stubs:0.0.1-SNAPSHOT] to /home/marcin/.m2/repository/com/example/{producer_artifact}/0.0.1-SNAPSHOT/{producer_artifact}-0.0.1-SNAPSHOT-stubs.jar
2017-05-11 12:16:51.322  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Unpacking stub from JAR [URI: file:/home/marcin/.m2/repository/com/example/{producer_artifact}/0.0.1-SNAPSHOT/{producer_artifact}-0.0.1-SNAPSHOT-stubs.jar]
2017-05-11 12:16:51.327  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Unpacked file to [/tmp/contracts9053257535983128167]
2017-05-11 12:16:52.608  INFO 4693 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@699e0bf0: startup date [Thu May 11 12:16:52 CEST 2017]; root of context hierarchy
2017-05-11 12:16:52.684  INFO 4693 --- [           main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
2017-05-11 12:16:52.837  INFO 4693 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8090 (http)
2017-05-11 12:16:52.851  INFO 4693 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2017-05-11 12:16:52.853  INFO 4693 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.14
2017-05-11 12:16:52.975  INFO 4693 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2017-05-11 12:16:52.975  INFO 4693 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 367 ms
2017-05-11 12:16:52.996  INFO 4693 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'stub' to [/]
2017-05-11 12:16:53.000  INFO 4693 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'admin' to [/__admin/*]
2017-05-11 12:16:53.135  INFO 4693 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8090 (http)
2017-05-11 12:16:53.139  INFO 4693 --- [           main] o.s.c.contract.stubrunner.StubServer     : Started stub server for project [com.example:{producer_artifact}:0.0.1-SNAPSHOT:stubs] on port 8090</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_beer_request">Beer Request</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">class BeerRequest {
	public int age;

	public BeerRequest(int age) {
		this.age = age;
	}

	public BeerRequest() {
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_missing_listener_code">Missing listener code</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">		if (verification.eligible) {
			this.eligibleCounter.incrementAndGet();
		} else {
			this.notEligibleCounter.incrementAndGet();
		}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_missing_triggers">Missing triggers</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">	@Test public void should_increase_the_eligible_counter_when_verification_was_accepted() throws Exception {
		int initialCounter = this.listener.eligibleCounter.get();

		//remove::start[]
		this.stubTrigger.trigger("accepted_verification");
		//remove::end[]

		then(this.listener.eligibleCounter.get()).isGreaterThan(initialCounter);
	}

	@Test public void should_increase_the_noteligible_counter_when_verification_was_rejected() throws Exception {
		int initialCounter = this.listener.notEligibleCounter.get();

		//remove::start[]
		this.stubTrigger.trigger("rejected_verification");
		//remove::end[]

		then(this.listener.notEligibleCounter.get()).isGreaterThan(initialCounter);
	}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_messaging_dsls">Messaging DSLs</h3>
<div class="listingblock primary">
<div class="title">Positive Verification</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// messaging/shouldSendAcceptedVerification.groovy
org.springframework.cloud.contract.spec.Contract.make {
	description("""
Sends a positive verification message when person is eligible to get the beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll send a message with a positive verification
```

""")
	// Label by means of which the output message can be triggered
	label 'accepted_verification'
	// input to the contract
	input {
		// the contract will be triggered by a method
		triggeredBy('clientIsOldEnough()')
	}
	// output message of the contract
	outputMessage {
		// destination to which the output message will be sent
		sentTo 'verifications'
		// the body of the output message
		body(
            eligible: true
		)
		headers {
			header("contentType", applicationJsonUtf8())
		}
	}
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Negative Verification</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// messaging/shouldSendRejectedVerification.groovy
org.springframework.cloud.contract.spec.Contract.make {
	description("""
Sends a negative verification message when person is not eligible to get the beer

```
given:
	client is too young
when:
	he applies for a beer
then:
	we'll send a message with a negative verification
```

""")
	// Label by means of which the output message can be triggered
	label 'rejected_verification'
	// input to the contract
	input {
		// the contract will be triggered by a method
		triggeredBy('clientIsTooYoung()')
	}
	// output message of the contract
	outputMessage {
		// destination to which the output message will be sent
		sentTo 'verifications'
		// the body of the output message
		body(
            eligible: false
		)
		headers {
			header("contentType", applicationJsonUtf8())
		}
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_producercontroller_implementation">ProducerController implementation</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">if (personCheckingService.shouldGetBeer(personToCheck)) {
    return new Response(BeerCheckStatus.OK);
}
return new Response(BeerCheckStatus.NOT_OK);</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_beerrestbase">BeerRestBase</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(MockitoJUnitRunner.class)
public abstract class BeerRestBase {
	@Mock PersonCheckingService personCheckingService;
	@InjectMocks ProducerController producerController;

	@BeforeEach
	public void setup() {
		given(personCheckingService.shouldGetBeer(argThat(oldEnough()))).willReturn(true);

		// https://github.com/spring-cloud/spring-cloud-contract/issues/1428
		EncoderConfig encoderConfig = new EncoderConfig().appendDefaultContentCharsetToContentTypeIfUndefined(false);
		RestAssuredMockMvc.config = new RestAssuredMockMvcConfig().encoderConfig(encoderConfig);
		RestAssuredMockMvc.standaloneSetup(producerController);
	}

	private TypeSafeMatcher&lt;PersonToCheck&gt; oldEnough() {
		return new TypeSafeMatcher&lt;PersonToCheck&gt;() {
			@Override protected boolean matchesSafely(PersonToCheck personToCheck) {
				return personToCheck.age &gt;= 20;
			}

			@Override public void describeTo(Description description) {

			}
		};
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_beermessagingbase">BeerMessagingBase</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(SpringRunner.class)
@SpringBootTest(classes = ProducerApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
@AutoConfigureMessageVerifier
@ImportAutoConfiguration(TestChannelBinderConfiguration.class)
public abstract class BeerMessagingBase {
	@Inject MessageVerifier messaging;
	@Autowired PersonCheckingService personCheckingService;

	@BeforeEach
	public void setup() {
		// let's clear any remaining messages
		// output == destination or channel name
		this.messaging.receive("output", 100, TimeUnit.MILLISECONDS);
	}

	public void clientIsOldEnough() {
		personCheckingService.shouldGetBeer(new PersonToCheck(25));
	}

	public void clientIsTooYoung() {
		personCheckingService.shouldGetBeer(new PersonToCheck(5));
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_messaging_implementation">Messaging implementation</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">		boolean shouldGetBeer = personToCheck.age &gt;= 20;
		this.source.send("output-out-0", new Verification(shouldGetBeer));
		return shouldGetBeer;</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_back_to_the_main_page">Back to the Main Page</h2>
<div class="sectionbody">
<div class="paragraph">
<p><a href="../workshops.html">Click here to go back to the main page</a></p>
</div>
</div>
</div>
</div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.js"></script>
<script>prettyPrint()</script>
</body>
</html>